﻿using System.Collections.Generic;
using HK.Core.Common;
using HK.Core.Load.Protocol.Data;
using HK.Core.Load.Protocol.Signal;
using HK.Core.Serializable.Protocol.Data;
using UnityEngine;

namespace HK.Core.Load.Data
{
    /// <summary>
    /// Ab信息
    /// </summary>
    public sealed class AbInfo : AssetBase, IAbInfo
    {
        
        /// <summary>
        /// AssetBundle Id
        /// <para>* 为所属AB包名，若非是从Ab包加载而来的，则为null</para>
        /// </summary>
        public string AbId => Key;
    
        /// <summary>
        /// Ab类型.
        /// </summary>
        public BundleType AbType { get; private set; } = BundleType.None;
    
        /// <summary>
        /// AssetBundle
        /// </summary>
        public AssetBundle Ab { get; private set; } = null;
    
        /// <summary>
        /// 设定Entity
        /// </summary>
        /// <param name="iType">Ab类型</param>
        /// <param name="iAb">Ab</param>
        /// <param name="iMainManifest">AssetBundle的主Manifest标志位</param>
        public void SetAb(BundleType iType, AssetBundle iAb, bool iMainManifest)
        {
            AbType = iType;
            Ab = iAb;
            MainManifest = iMainManifest;
        }
    
        /// <summary>
        /// AssetBundle的主Manifest标志位
        /// </summary>
        public bool MainManifest { get; private set; } = false;
    
        /// <summary>
        /// 默认资源标志位
        /// </summary>
        public bool IsDefault { get; private set; } = false;

        /// <summary>
        /// Ab卸载时，全部Unload标志位
        /// </summary>
        public bool UnloadAll { get; private set; } = false;
    
        /// <summary>
        /// 数据大小(单位：Byte)
        /// </summary>
        public long DataSize { get; private set; } = 0L;
    
        /// <summary>
        /// 版本号
        /// </summary>
        public ISAssetVersion Version { get; private set; } = null;
        
        /// <summary>
        /// 设定信息
        /// </summary>
        /// <param name="iAbId">AbId</param>
        /// <param name="iOptions">选项</param>
        /// <param name="iAsync">异步标志位</param>
        /// <param name="iUnloadAll">Ab卸载时，是否全部卸载标志位</param>
        /// <param name="iCoolTime">倒计时冷却时间(默认 : 30秒)</param>
        public void SetInfo(string iAbId, int iOptions, bool iAsync = false, 
            bool iUnloadAll = false, float iCoolTime = Const.DefaultCoolTime)
        {
            // 设定信息
            SetInfo(iAbId, iOptions, iAsync, iCoolTime);
            UnloadAll = iUnloadAll;
        }

#region Depends

        /// <summary>
        /// 依赖列表
        /// <para>* 用以反向索引所属依赖关系用</para>
        /// </summary>
        public List<IAbInfo> Depends { get; private set; } = null;

        /// <summary>
        /// 更新依赖信息
        /// </summary>
        /// <param name="iDepends">依赖列表</param>
        public void UpdateDepends(List<IAbInfo> iDepends)
        {
            Depends = iDepends;
        }

#endregion

#region Use&UnUse

        /// <summary>
        /// 使用
        /// <para>* 每使用一次，该引用计数会自增一</para>
        /// </summary>
        public override void Use()
        {
            var dCount = Depends.Count;
            for (var idx = 0; idx < dCount; ++idx)
            {
                var depend = Depends[idx];
                if(null == depend || !depend.Valid) continue;
                
                depend.Use();
            }

            base.UnUse();

        }

        /// <summary>
        /// 撤销使用
        /// <para>* 每撤销一次，该引用计数会自减一, 当引用计数小于等于0时，会自动释放或者触发倒计时释放</para>
        /// </summary>
        /// <param name="iForce">强制标志位(会强制将引用计数清零，后强制释放)</param>
        public override void UnUse(bool iForce = false)
        {
            var dCount = Depends.Count;
            for (var idx = 0; idx < dCount; ++idx)
            {
                var depend = Depends[idx];
                if(null == depend || !depend.Valid) continue;
                
                depend.UnUse(false);
            }
            
            base.UnUse(iForce);
        }

#endregion
    
        /// <summary>
        /// 释放自身
        /// </summary>
        /// <returns>true:释放成功; false:释放失败;</returns>
        protected override bool ReleaseSelf()
        {
            if (null != Ab)
            {
                Ab.Unload(UnloadAll);
                Ab = null;
            }
            return true;
        }
        
    }
}